점프 게임

그동안 카드 뒤집어서 짝맞추기, 지뢰찾기 등 게임 몇 개를 만들어봤는데 디자인에는 크게 신경을 쓰지 않았었다. 기능이 중요하지!! 하면서… 그렇지만 오늘은 유튜브에서 본 간단한 점프게임을 만들면서 이쁘게 꾸며보았다. 흡족하다. 이미지는 Pixabay에서 다운받았다. 만들면서 든 생각인데 슈퍼마리오 클론코딩하면 엄청 재밌을 것 같다.
호스팅은 파이어베이스를 이용했다.

게임하기 및 소스

(클릭 시 새 창에 뜹니다.)

https://jump-game-ac50b.web.app/

깃헙 소스코드

게임화면

시작화면

폭탄이 다가오면 점프! 마우스로 화면을 클릭하면 된다.

게임이 끝나면 애니메이션이 멈추고 게임오버 텍스트가 뜬다.

코드 설명

만들면서 신경 쓴 부분들을 중점으로 설명해 보겠습니다.

HTML

<body>
  <div id="game">
    <div id="jumpNum" class="hidden">성공 × <span>0</span></div>
    <div id="gameover" class="hidden">GAME OVER</div>
    <button id="btn">Start</button>
    <div id="character"></div>
    <div id="bomb"></div>
  </div>
</body>

html은 간단하다. 캐릭터와 폭탄은 div에 background-img로 넣어주었다.

CSS

게임오버 텍스트

#gameover {
  position: absolute;
  top: 100px;
  left: 50%;
  transform: translateX(-50%);
  font-size: 3rem;
  font-weight: bolder;
  filter: drop-shadow(2px 2px rgb(124, 97, 97));
  animation: twinkle 0.5s linear 2;
}
@keyframes twinkle {
  0% {
    opacity: 0.2;
  }
  50% {
    opacity: 1;
  }
  100% {
    opacity: 0.2;
  }
}

레딧에서 누군가 말했었다. 본인 프로젝트에 음 뭔가 부족한데.. 싶으면 shadow를 추가해보라고. 그걸 본 뒤로 잘 애용하고 있다.
텍스트가 화면의 가운데에 있어야 하기 때문에 left: 50%, transform: translateX(-50%) 를 주었다.
애니메이션을 주어서 게임오버 텍스트가 빤짝빤짝 빛나게 했다.

캐릭터 이미지

#character {
  position: relative;
  top: 203px;
  left: -55px;
  background: url('./images/pacman.png') -357px -178px no-repeat;
  width: 250px;
  height: 270px;
  transform: scale(0.45);
}
.jump {
  animation: jump 1s ease;
}
@keyframes jump {
  0% {
    top: 203px;
  }
  50% {
    top: 110px;
  }
  75% {
    top: 110px;
  }
  100% {
    top: 203px;
  }
}

background position을 조정해서 이미지 스프라이트를 하였다.
jump 클래스를 넣었다 붙였다 하면서 캐릭터가 점프하도록 만들 것이다.
jump 애니메이션에 50%와 75%를 똑같이 준 이유는 붕~ 뜨고 잠시 있다가 가라앉는 모션을 위해서이다.

Javascript

start 버튼 누를 때

startBtn.addEventListener('click', e => {
  e.stopPropagation()
  stopflag = false
  bomb.classList.add('move')
  gameoverText.classList.add('hidden')
  startBtn.classList.add('hidden')
  jumpNum.classList.remove('hidden')
  jumpNumCnt.textContent = 0
})

stopPropagation() 을 줘서 start 버튼을 눌렀을 때 그 이벤트가 부모로 전달이 되지 않게끔 막았다. 이 코드를 삭제한다면 start 버튼을 누르면 캐릭터가 점프한다. 왜냐면 화면 아무 곳이나 누르면 점프하기 때문이다. 이 코드로 시작버튼을 클릭할 때 엄하게 캐릭터가 뛰는 것을 막을 수 있다.

게임오버 글씨나 재시작 버튼은 게임이 끝나면 보이고 시작하면 사라지도록 hidden 클래스를 넣었다 뺐다 한다. hidden 클래스에는 display: none 을 넣어주었다.

게임화면 클릭할 때 (점프!)

game.addEventListener('click', e => {
  if (!stopflag) {
    character.classList.add('jump')
    stopflag = true
    jumpNumCnt.textContent++
  } else if (stopflag) {
    return
  }

  // 연속으로 캐릭터가 뛰지 않도록 조절
  setTimeout(() => {
    character.classList.remove('jump')
    stopflag = false
  }, 1000)
})

클릭! -> 캐릭터 점프 시작 -> 착지. 점프 시작과 착지 사이에 또 클릭이 먹히면 안 된다. 그래서 stopflag 를 주어서 stopflag 가 true 라면 클릭을 무시하도록 return 을 주었다.

setTimeout 으로 1초 뒤에 jump 클래스를 제거했다.

캐릭터와 폭탄이 닿았을 때

setInterval(() => {
  let characterTop = parseInt(
    window.getComputedStyle(character).getPropertyValue('top')
  )
  let bombLeft = parseInt(
    window.getComputedStyle(bomb).getPropertyValue('left')
  )
  // 졌다.
  if (characterTop > 180 && bombLeft < -470) {
    stopflag = true
    bomb.classList.remove('move')
    gameoverText.classList.remove('hidden')
    startBtn.textContent = 'Replay'

    setTimeout(() => {
      startBtn.classList.remove('hidden')
    }, 1000)
  }
}, 100)

setInterval로 0.1초마다 캐릭터와 폭탄이 닿았는지 확인한다.
window.getComputedStyle()은 괄호 안의 css style 을 가져온다. 캐릭터의 높이와 폭탄의 좌측거리를 계산해서 충분히 높이 뛰지 않았는데 폭탄이 올 경우 게임이 종료된다.

게임이 종료될 때 바로 성공횟수를 0으로 초기화하면 사용자가 놓칠 수 있어서 재시작버튼을 누를 때 초기화하도록 했다.


Written by@Jiyon Lee
뜨거운 코드를 가르며

GitHub